package com.qisu.socket.server;

import java.net.InetSocketAddress;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;

import com.qisu.AppInit;

import cn.hutool.log.Log;
import cn.hutool.log.LogFactory;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.nio.NioEventLoopGroup;

/****
 *
 * @author alsan
 *
 */
@Component
@Configuration
public class NettyServer implements ApplicationContextAware {
	private Log log = LogFactory.get();
	private Channel channel;

	@Autowired AppInit appInit;
	@Autowired ServerBootstrap serverBootstrap;
	@Autowired @Qualifier("tcpSocketAddress") private InetSocketAddress tcpPort;
	@Autowired @Qualifier("masterGroup") private NioEventLoopGroup masterGroup;
	@Autowired @Qualifier("workerGroup") private NioEventLoopGroup workerGroup;

	@PostConstruct
	public void start() {
		try {
			ChannelFuture future = serverBootstrap.bind(tcpPort).sync();

			if(future.isSuccess()) {
				log.info("server startup successfully, listening on port: " + tcpPort.getPort());
				channel = future.channel().closeFuture().sync().channel();
			} else {
				log.error("Unable to start server");
			}
		} catch(InterruptedException e) {
			log.error(e.getMessage());
		} finally {
			stop();
		}
	}

	@PreDestroy
	public void stop() {
		if(null != workerGroup) {
			workerGroup.shutdownGracefully();
		}
		if(null != masterGroup) {
			masterGroup.shutdownGracefully();
		}
		if(null != channel) {
			channel.close();
		}

		log.info("server shutdown gracefully");
	}

	@Override
	public void setApplicationContext(ApplicationContext ctx) throws BeansException {
		log.debug("setting application context");

		try {
			appInit.run();
		} catch(Exception e) {
			e.printStackTrace();
		}
	}
}
